package top.suyarong.ftbqsync.data;


import com.tanxi521.tnlevel.dao.ConnectionPool;
import org.bukkit.entity.Player;
import top.suyarong.ftbqsync.FTBQSync;
import top.suyarong.ftbqsync.data.entity.FtbQuestSync;
import top.suyarong.ftbqsync.utils.LogUtil;

import java.sql.*;

public class FtbMapper {

    private static final LogUtil log = LogUtil.getInstance();

    private static final FTBQSync plugin = FTBQSync.getInstance();

    private FtbMapper() {
    }

    private static volatile FtbMapper instance;

    public static synchronized FtbMapper getInstance() {
        if (instance == null) {
            synchronized (FtbMapper.class) {
                if (instance == null) {
                    instance = new FtbMapper();
                }
            }
        }
        return instance;
    }

    public void createTable() {
        Connection connection = ConnectionPool.getConnection();
        PreparedStatement statement = null;
        try {
            statement = connection.prepareStatement(SQLEnum.CREATE_TABLE.getSql());
            statement.execute();
        } catch (SQLException e) {
            e.printStackTrace();
            log.warn(plugin, "初始化数据失败");
        } finally {
            try {
                if (statement != null) statement.close();
                ConnectionPool.returnSource(connection);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public FtbQuestSync getPlayerData(Player player) {
        String playerName = player.getName();
        Connection connection = ConnectionPool.getConnection();
        PreparedStatement statement = null;
        ResultSet rs = null;

        try {
            statement = connection.prepareStatement(SQLEnum.GET_PLAYER_DATA.getSql());
            statement.setString(1, playerName);
            rs = statement.executeQuery();
            if (!rs.next()) return null;

            return FtbQuestSync.builder()
                    .id(rs.getInt("id"))
                    .playerName(rs.getString("player_name"))
                    .ftbData(rs.getBytes("ftb_data"))
                    .astralData(rs.getBytes("astral_data"))
                    .createTime(rs.getDate("create_time"))
                    .updateTime(rs.getDate("update_time"))
                    .build();

        } catch (SQLException e) {
            e.printStackTrace();
            log.warn(plugin, "获取用户 {0} 数据失败", playerName);
        } finally {

            try {
                if (statement != null) statement.close();
                if (rs != null) rs.close();
                ConnectionPool.returnSource(connection);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return null;
    }

    public boolean checkPlayerExist(Player player) {
        String playerName = player.getName();
        Connection connection = ConnectionPool.getConnection();
        PreparedStatement statement = null;
        ResultSet rs = null;

        try {
            statement = connection.prepareStatement(SQLEnum.CHECK_EXIST.getSql());
            statement.setString(1, playerName);
            rs = statement.executeQuery();
            if (!rs.next()) return false;
            int count = rs.getInt(1);
            return count > 0;
        } catch (SQLException e) {
            e.printStackTrace();
            log.warn(plugin, "获取用户 {0} 数据失败", playerName);
        } finally {
            try {
                if (statement != null) statement.close();
                if (rs != null) rs.close();
                ConnectionPool.returnSource(connection);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return false;
    }

    public int insertNewPlayer(FtbQuestSync ftbQuestSync) {
        Connection connection = ConnectionPool.getConnection();
        PreparedStatement statement = null;
        String playerName = ftbQuestSync.getPlayerName();
        try {
            statement = connection.prepareStatement(SQLEnum.NEW_PLAYER_DATA.getSql());
            statement.setString(1, playerName);
            statement.setBytes(2, ftbQuestSync.getFtbData());
            statement.setBytes(3, ftbQuestSync.getAstralData());
            return statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            log.warn(plugin, "用户 {0} 数据插入失败", playerName);
        } finally {
            try {
                if (statement != null) statement.close();
                ConnectionPool.returnSource(connection);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return -1;
    }

    public int updatePlayer(FtbQuestSync ftbQuestSync) {
        Connection connection = ConnectionPool.getConnection();
        PreparedStatement statement = null;
        String playerName = ftbQuestSync.getPlayerName();
        try {
            statement = connection.prepareStatement(SQLEnum.UPDATE_PLAYER_DATA.getSql());
            statement.setBytes(1, ftbQuestSync.getFtbData());
            statement.setBytes(2, ftbQuestSync.getAstralData());
            statement.setString(3, playerName);
            return statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            log.warn(plugin, "用户 {0} 数据更新失败", playerName);
        } finally {
            try {
                if (statement != null) statement.close();
                ConnectionPool.returnSource(connection);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return -1;
    }

    public int lockPlayer(FtbQuestSync ftbQuestSync) {
        Connection connection = ConnectionPool.getConnection();
        PreparedStatement statement = null;
        String playerName = ftbQuestSync.getPlayerName();
        try {
            statement = connection.prepareStatement(SQLEnum.LOCK_PLAYER.getSql());
            statement.setString(1, playerName);
            return statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            log.warn(plugin, "锁定 {0} 数据更新失败", playerName);
        } finally {
            try {
                if (statement != null) statement.close();
                ConnectionPool.returnSource(connection);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return -1;
    }

}
